package com.example.backend.util;

import com.example.backend.domain.entity.Comment;
import com.example.backend.domain.entity.Feedback;
import com.example.backend.domain.entity.Ticket;
import com.example.backend.domain.entity.User;
import com.example.backend.domain.enums.Role;

/**
 * 数据权限过滤工具类
 * 用于在Service层进行数据级别的权限控制
 * 
 * 使用示例：
 * <pre>
 * {@code
 * public TicketDto getTicket(Long id, User currentUser) {
 *     Ticket ticket = ticketRepository.findById(id)
 *         .orElseThrow(() -> new RuntimeException("工单不存在"));
 *     
 *     // 检查数据权限
 *     if (!DataPermissionUtils.canAccessTicket(currentUser, ticket)) {
 *         throw new AccessDeniedException("无权访问此工单");
 *     }
 *     
 *     return convertToDto(ticket);
 * }
 * }
 * </pre>
 */
public class DataPermissionUtils {
    
    /**
     * 检查用户是否可以访问指定工单
     * 
     * @param user 当前用户
     * @param ticket 工单
     * @return true表示有权限，false表示无权限
     */
    public static boolean canAccessTicket(User user, Ticket ticket) {
        if (user == null || ticket == null) {
            return false;
        }
        
        Role role = user.getRole();
        
        return switch (role) {
            // 管理员和主管可以访问所有工单
            case ADMIN, SUPERVISOR -> true;
            
            // 客服可以访问分配给自己的工单
            case AGENT -> ticket.getAssignedTo() != null && 
                         ticket.getAssignedTo().getId().equals(user.getId());
            
            // 客户只能访问自己创建的工单
            case CUSTOMER -> ticket.getCustomer() != null &&
                            ticket.getCustomer().getId().equals(user.getId());
            
            // 只读用户可以查看所有工单（如果有ticket:read权限）
            case READONLY -> true;
            
            default -> false;
        };
    }
    
    /**
     * 检查用户是否可以修改指定工单
     * 
     * @param user 当前用户
     * @param ticket 工单
     * @return true表示有权限，false表示无权限
     */
    public static boolean canModifyTicket(User user, Ticket ticket) {
        if (user == null || ticket == null) {
            return false;
        }
        
        Role role = user.getRole();
        
        return switch (role) {
            // 管理员和主管可以修改所有工单
            case ADMIN, SUPERVISOR -> true;
            
            // 客服可以修改分配给自己的工单
            case AGENT -> ticket.getAssignedTo() != null && 
                         ticket.getAssignedTo().getId().equals(user.getId());
            
            // 客户可以修改自己创建的且未关闭的工单
            case CUSTOMER -> ticket.getCustomer() != null &&
                            ticket.getCustomer().getId().equals(user.getId()) &&
                            !ticket.getStatus().name().equals("CLOSED");
            
            // 只读用户不能修改任何工单
            case READONLY -> false;
            
            default -> false;
        };
    }
    
    /**
     * 检查用户是否可以删除指定工单
     * 
     * @param user 当前用户
     * @param ticket 工单
     * @return true表示有权限，false表示无权限
     */
    public static boolean canDeleteTicket(User user, Ticket ticket) {
        if (user == null || ticket == null) {
            return false;
        }
        
        Role role = user.getRole();
        
        return switch (role) {
            // 只有管理员可以删除工单
            case ADMIN -> true;
            
            // 主管可以删除未分配的工单
            case SUPERVISOR -> ticket.getAssignedTo() == null;
            
            // 其他角色不能删除工单
            default -> false;
        };
    }
    
    /**
     * 检查用户是否可以分配工单
     * 
     * @param user 当前用户
     * @param ticket 工单
     * @return true表示有权限，false表示无权限
     */
    public static boolean canAssignTicket(User user, Ticket ticket) {
        if (user == null || ticket == null) {
            return false;
        }
        
        Role role = user.getRole();
        
        return switch (role) {
            // 管理员、主管、客服可以分配工单
            case ADMIN, SUPERVISOR, AGENT -> true;
            
            // 其他角色不能分配工单
            default -> false;
        };
    }
    
    /**
     * 检查用户是否可以访问指定反馈
     * 
     * @param user 当前用户
     * @param feedback 反馈
     * @return true表示有权限，false表示无权限
     */
    public static boolean canAccessFeedback(User user, Feedback feedback) {
        if (user == null || feedback == null) {
            return false;
        }
        
        Role role = user.getRole();
        
        return switch (role) {
            // 管理员和主管可以访问所有反馈
            case ADMIN, SUPERVISOR -> true;
            
            // 客服可以访问其有权访问的工单的反馈
            case AGENT -> feedback.getTicket() != null && 
                         canAccessTicket(user, feedback.getTicket());
            
            // 客户可以访问自己创建的反馈，或其能访问的工单下的反馈
            case CUSTOMER -> (feedback.getAuthor() != null &&
                             feedback.getAuthor().getId().equals(user.getId())) ||
                             (feedback.getTicket() != null &&
                             canAccessTicket(user, feedback.getTicket()));
            
            // 只读用户可以访问其有权访问的工单的反馈
            case READONLY -> feedback.getTicket() != null &&
                            canAccessTicket(user, feedback.getTicket());
            
            default -> false;
        };
    }
    
    /**
     * 检查用户是否可以访问指定评论
     * 
     * @param user 当前用户
     * @param comment 评论
     * @return true表示有权限，false表示无权限
     */
    public static boolean canAccessComment(User user, Comment comment) {
        if (user == null || comment == null) {
            return false;
        }
        
        Role role = user.getRole();
        
        // 内部评论只有内部人员可见
        if (comment.getIsInternal()) {
            return role == Role.ADMIN || 
                   role == Role.SUPERVISOR || 
                   role == Role.AGENT;
        }
        
        return switch (role) {
            // 管理员和主管可以访问所有评论
            case ADMIN, SUPERVISOR -> true;
            
            // 客服可以访问与自己相关工单的评论
            case AGENT -> comment.getTicket() != null && 
                         comment.getTicket().getAssignedTo() != null &&
                         comment.getTicket().getAssignedTo().getId().equals(user.getId());
            
            // 客户可以访问自己工单的非内部评论
            case CUSTOMER -> comment.getTicket() != null &&
                            comment.getTicket().getCustomer() != null &&
                            comment.getTicket().getCustomer().getId().equals(user.getId()) &&
                            !comment.getIsInternal();
            
            // 只读用户可以查看非内部评论
            case READONLY -> !comment.getIsInternal();
            
            default -> false;
        };
    }
    
    /**
     * 检查用户是否可以修改指定评论
     * 
     * @param user 当前用户
     * @param comment 评论
     * @return true表示有权限，false表示无权限
     */
    public static boolean canModifyComment(User user, Comment comment) {
        if (user == null || comment == null) {
            return false;
        }
        
        Role role = user.getRole();
        
        return switch (role) {
            // 管理员可以修改所有评论
            case ADMIN -> true;
            
            // 其他用户只能修改自己的评论
            default -> comment.getAuthor() != null &&
                      comment.getAuthor().getId().equals(user.getId());
        };
    }
    
    /**
     * 检查用户是否可以访问其他用户信息
     * 
     * @param currentUser 当前用户
     * @param targetUser 目标用户
     * @return true表示有权限，false表示无权限
     */
    public static boolean canAccessUserInfo(User currentUser, User targetUser) {
        if (currentUser == null || targetUser == null) {
            return false;
        }
        
        // 用户可以访问自己的信息
        if (currentUser.getId().equals(targetUser.getId())) {
            return true;
        }
        
        Role role = currentUser.getRole();
        
        return switch (role) {
            // 管理员和主管可以访问所有用户信息
            case ADMIN, SUPERVISOR -> true;
            
            // 客服可以访问基本用户信息（不包括敏感信息）
            case AGENT -> true;
            
            // 客户和只读用户只能访问自己的信息
            default -> false;
        };
    }
    
    /**
     * 检查用户是否可以修改其他用户信息
     * 
     * @param currentUser 当前用户
     * @param targetUser 目标用户
     * @return true表示有权限，false表示无权限
     */
    public static boolean canModifyUserInfo(User currentUser, User targetUser) {
        if (currentUser == null || targetUser == null) {
            return false;
        }
        
        Role role = currentUser.getRole();
        
        return switch (role) {
            // 管理员可以修改所有用户信息
            case ADMIN -> true;
            
            // 主管可以修改客服和客户的信息，但不能修改管理员
            case SUPERVISOR -> targetUser.getRole() != Role.ADMIN;
            
            // 其他用户只能修改自己的信息（不包括角色等敏感字段）
            default -> currentUser.getId().equals(targetUser.getId());
        };
    }
}

